# -*- coding: utf8 -*-

__author__ = 'sergey'

import traceback
from time import sleep
from datetime import datetime
from threading import Thread, Event
from Queue import Queue
from multiprocessing import cpu_count


class FindDupImagesVectors(Thread):
    """
    __init__ : args = ( parent_thread, db_req )
    """

    db_req = None

    stop_event = None
    queue = None
    parent = None

    item_count = 0
    processed_count = 0

    number = 0

    log = None

    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, verbose=None):
        self.parent, self.db_req, self.number = args
        self.stop_event = Event()
        self.queue = Queue()
        Thread.__init__(self, group, target, name, args, kwargs, verbose)

    def run(self):
        from logger import get_file_logger
        self.log = get_file_logger("worker-FindDupImagesVectors-%s" % self.number)

        from libc import set_affinity

        try:

            set_affinity(0, 2**(self.number % cpu_count()))

            self.find_dupimages_vectors()
        except Exception as e:
            self.log.error(e)
            self.log.error(traceback.format_exc())
        return 0

    def add_image(self, item):
        self.item_count += 1
        self.queue.put_nowait(item)
        return self

    def empty(self):
        return self.item_count == self.processed_count

    def stop(self):
        self.stop_event.set()
        return self

    def find_dupimages_vectors(self):

        self.log.info("START")

        from images.vector import compare_vectors

        if not self.parent.images_count:
            self.log.info("STOP")
            return 0

        while not self.stop_event.isSet():

            try:
                item = self.queue.get_nowait()
            except Exception:
                item = None

            if item is None:
                sleep(0.01)
                continue

            self.log.debug("Item=%r" % item)

            item_v10 = self.db_req.query("get_image_vectors10", (item["id"],))
            # self.log.debug("Item vector 10=%r" % item_v10)

            gray_ids = ()

            self.log.debug("-- Get images gray like...")
            t1 = datetime.now()

            for v10 in item_v10:
                ids_req = self.db_req.query("get_similar_images10", (v10,), no_return=True )
                while not self.db_req.has_result(ids_req):
                    if self.stop_event.isSet():
                        break
                    sleep(0.01)
                #t2 = datetime.now()
                #self.log.debug("Got images gray like in %s" % (t2 - t1))

                #t1 = datetime.now()
                while True:
                    if self.stop_event.isSet():
                        break
                    ids_row = self.db_req.get_result_row(ids_req)
                    if ids_row is None:
                        break
                    if ids_row and ids_row['image_id'] and not gray_ids.count(ids_row['image_id']):
                        gray_ids += (ids_row['image_id'],)

            t2 = datetime.now()
            self.log.debug("-- Fetch images gray like: %s, in %s" % (len(gray_ids), t2 - t1))

            gray_count = len(gray_ids)


            item_v100 = None
            # self.log.debug("Item vector 100=%r" % item_v100)

            if not gray_count:
                self.parent.inc_processed(1)

            for img_id in gray_ids:

                if self.stop_event.isSet():
                    break

                self.parent.inc_processed( 1.0 / gray_count )

                self.parent.update_ui()

                # self.log.debug("Item gray id=%r" % img_id)

                if img_id == item["id"]:
                    self.log.debug("-- Item gray id == item id")
                    continue

                # self.log.debug("Item gray compare with item...")
                if self.db_req.query("has_image2image", (item["id"], img_id,)):
                    self.log.debug("-- Item gray compared with item")
                    continue

                img = self.db_req.query("get_image", (img_id,))

                if not img:
                    self.log.debug("-- Image not found by id! Deleted?")
                    continue

                if img["file_id"] == item["file_id"]:
                    self.log.debug("-- Item gray file_id == item file_id")
                    continue

                # self.log.debug("Item gray get vectors 100")
                img_v100 = self.db_req.query("get_image_vectors100", (img_id,))

                if not item_v100:
                    item_v100 = self.db_req.query("get_image_vectors100", (item["id"],))

                # self.log.debug("Item gray vectors 100=%r" % img_v100)

                sim = 0
                comp = (0,)

                if img_v100 and item_v100:
                    for j in range(len(item_v100)):

                        if self.stop_event.isSet():
                            break

                        v100_1 = item_v100[j]["vector"]

                        for i in range(len(img_v100)):

                            if self.stop_event.isSet():
                                break

                            v100_2 = img_v100[i]["vector"]

                            comp += ( compare_vectors(v100_1, v100_2, 0.05) , )
                            # self.log.debug("Item gray compared vs 100=%r" % (comp,))
                            if max(comp) >= 95:
                                sim += 1
                                break

                        if max(comp) >= 95:
                            break

                q_point = 0
                if sim:

                    self.log.debug("-- found similar item=%r" % img)

                    if item["mime"] != img["mime"]:
                        if item["mime"] == "image/png":
                            q_point += 1
                        if img["mime"] == "image/png":
                            q_point -= 1
                    else:
                        if int(item["size"]) > int(img["size"]):
                            q_point += 1
                        else:
                            q_point -= 1

                    if int(item["width"])*int(item["height"]) > int(img["width"])*int(img["height"]):
                        q_point += 1
                    else:
                        q_point -= 1

                    if int(item["is_gray"]) > int(img["is_gray"]):
                        q_point += 1
                    else:
                        q_point -= 1


                    self.log.debug("-- equal by %s, quality points: %s" % (max(comp), q_point,))
                    self.db_req.query("insert_image2image", (item["id"], img_id, item["file_id"], img["file_id"], max(comp), q_point,))

                    """
                    self.parent.add_image_to_treeview( item, img, {
                        "image1_id":item["id"],
                        "image2_id":img["id"],
                        "equal_proc":max(comp),
                        "quality_points":q_point
                    })
                    """

                    self.parent.inc_similar()


                    file2file = self.db_req.query("has_file2file", (item["file_id"], img["file_id"], ))
                    self.log.debug("-- has File2File: %r" % (file2file,))
                    if not file2file:

                        file1_count = self.db_req.query("get_images_in_file_count", (item["file_id"],))
                        file2_count = self.db_req.query("get_images_in_file_count", (img["file_id"],))

                        self.log.debug("-- file 1 = %s, file 2 = %s" % (item["file_id"], img["file_id"],))
                        self.log.debug("-- images count 1 = %s, images count 2 = %s" % (file1_count, file2_count,))

                        self.db_req.query("insert_file2file", (
                            item["file_id"], img["file_id"], file1_count, file2_count,
                        ))
                    else:
                        if file2file["reverse"]:
                            q_point *= -1
                        self.log.debug("-- inc count and add quality points")
                        self.db_req.query("inc_file2file", ( file2file["id"], q_point,))


                    self.parent.update_ui()
                else:
                    # self.log.debug("Images compared: %s, quality points: %s" % (max(comp), q_point,))
                    self.db_req.query("insert_image2image", (item["id"], img_id, item["file_id"], img["file_id"], max(comp), q_point,))

                # self.log.debug("-- Next Item gray...")

            self.parent.update_ui()

            self.processed_count += 1

            self.queue.task_done()

            pass

        self.parent.update_ui()


        self.log.info("STOP")

        self.stop_event.clear()

        return
